home *** CD-ROM | disk | FTP | other *** search
- Text and code for a contouring algorithm, wrote it a long time ago but it is
- still useful. If you want the image see the June or July 1987 Byte article.
-
- CONREC - A Contouring Subroutine
- Written by Paul D. Bourke (MSc.)
-
- Introduction
- This article introduces a straightforward method of contouring some surface.
- The algorithm is implemented in a subroutine written in BASIC.
- Contouring aids in visualizing three dimensional surfaces on a two
- dimensional medium (on paper or in this case a computer graphics screen).
- Two most common applications are displaying topological features of an area
- on a map or the air pressure on a weather map. In all cases some parameter
- is plotted as a function of two variables, the longitude and latitude or x
- and y axis. One problem with computer contouring is the process is usually
- CPU intensive and the algorithms often using advanced mathematical
- techniques.
-
- CONREC
- To do contouring in software you need to describe the data surface and the
- contour levels you want to have drawn. The software given this information
- must call the algorithm that calculate sthe line segments that make up a
- contour curve and then plot these line segments on whatever graphics device
- is available.
- CONREC satisfies the above description, it is relatively simple to
- implement, very reliable, and does not require sophisticated programming
- techniques or a high level of mathematics to understand how it works.
- The input parameters to the CONREC subroutine are as follows :
- - The number of horizontal and vertical data points designated iub and jub.
- - The number of contouring levels, nc.
- - A one dimensional array z(0:nc-1) that seves as a list of the contour
- levels in increasing order. (The order of course can be relaxed if the
- program will sort the levels)
- - A two dimensional array d(0:iub,0:jub) that contains the description of
- the data array to be contoured. Each element of the array is a sample of
- the surface being studied at a point (x,y)
- - Two, one dimensional arrays x(0:iub) and y(0:jub) which contain the
- horizontal and vertical coordinates of each sample point. This allows for a
- rectangular grid of samples. Diagram 0 illustates some of the above input
- parameters.
-
- The contouring subroutine CONREC does not assume anything about the device
- that will be used to plot the contours. It instead expects a user written
- subroutine called VECOUT. CONREC calls VECOUT with the horizontal and
- vertical coordinates of the start and end coordinates of a line segment
- along with the contour level for that line segment. In the simplest case
- this is very similar the the usual LINE (x1,y1)-(x2,y2) command in BASIC.
- See examples.
-
- Algorithm
- As already mentioned the samples of the three dimensional surface are stored
- in a two dimensional real array. This rectangular grid is considered four
- points at a time, namely the rectangle d(i,j), d(i+1,j), d(i,j+1), and
- d(i+1,j+1). The centre of each rectangle is assigned a value corresponding
- to the average values of each of the four vertices. Each rectangle is in
- turn divided into four triangular regions by cutting along the diagonals.
- Each of these triangular planes may be bisected by horizontal contour plane.
- The intersection of these two planes is a straight line segment, part of
- the the contour curve at that contour height.
- Depending on the value of a contour level with respect to the height at the
- vertices of a triangle, certain types of contour lines are drawn. The 10
- possible cases which may occur are summarised below (also see table 1)
- a) All the vertices lie below the contour level.
- b) Two vertices lie below and one on the contour level.
- c) Two vertices lie below and one above the contour level.
- d) One vertex lies below and two on the contour level.
- e) One vertex lies below, one on and one above the contour level.
- f) One vertex lies below and two above the contour level.
- g) Three vertices lie on the contour level.
- h) Two vertices lie on and one above the contour level.
- i) One vertex lies on and two above the contour level.
- j) All the vertices lie above the contour level.
-
- In cases a, b, i and j the two planes do not intersect, ie: no line need be
- drawn. For cases d and h the two planes intersect along an edge of the
- triangle and therefore line is drawn between the two vertices that lie on
- the contour level. Case e requires that a line be drawn from the vertex on
- the contour level to a point on the opposite edge. This point is determined
- by the intersection of the contour level with the straight line between the
- other two vertices. Cases c and f are the most common situations where the
- line is drawn from one edge to another edge of the triangle. The last
- possibility or case g above has no really satisfactory solution and
- fortunately will occur rarely with real arithmetic. Diagram 2 summarises
- the possible line orientations.
-
- Example
- As a simple example consider one triangle with vertices labelled m1,m2 and
- m3 with heights 0,2 and 3 respectively (See diagram 3) To calculate where a
- contour line at a height of 1 should be drawn, it can be seen that this is
- case f described above. Level 1 intersects line segment m1-m2 half the way
- along and it intersects line segment m1-m3 one third of the way along. A
- line segment is drawn between these two points.
-
- Subroutine
- In summary, CONREC takes each rectangle of adjacent data points and splits
- it into 4 triangles after chooseing the height at the centre of the
- rectangle. For each of the triangles the line segment resulting from the
- intersection with each contour plane. A routine is then called with the
- starting and stopping coordinates of the line segment. Listing 1 shows the
- CONREC subroutine written in MicroSoft Basic (version 2 binary) for the
- Macintosh. An attempt is made at optimization by checking first to see if
- there are any contour levels within the present rectangle and second that
- there are some contour levels within the present triangle. The indices i
- and j are used to step through each rectangle in turn, k refers to each
- contour level and m to the four triangles in each rectangle. Diagram 1
- gives some of the notation used for identifying the rectangles and
- triangles in the subroutine.
- Note that for large arrays the whole data array need be stored in memory .
- Since the algorithm is a local one only requiring 4 points at a time, the
- data for each rectangle could be read from disk when required.
-
- Improvements
- You can add features such as labeling the contour and axes, drawing the
- contour lines with different colours or in the case of a black and white
- display, drawing the contour lines with different mark-space ratio's. The
- contours may be labeled with the contour values either by software or by
- adding them later by hand.
-
-
- Examples of CONREC
-
- Example 1 is a program that uses CONREC to draw the contour of a
- mathematical function. The function is given by
- 1
- f ( x , y ) = sin ( ( x2 + y2 )1/2 ) + ----------------
- ( ( x - c )2 + y2 )1/2
-
- Example 2 is taken from physics. The potential a distance r from the origin
- from two charges q1 and q2, located at plus and minus c is given by
- q1 q2
- V( x , y ) = const * ( --- - --- )
- r1 r2
- where r1 and r2 are the distances from the point ( x , y ) to the charge q1
- and q2 respectively. Contouring this function gives rise to equipotential
- surfaces, Similar functions also arise in the case of gravitational
- potentials.
-
- Example 3 is a contour diagram of the function
- 1
- f( x , y ) = -------------------------------------------------
- ((x2+(y-0.842)(y+0.842))2 + (x(y-0.842) + x(y-0.842))2
-
- Example 4 is a contour diagram of cowboy hat shaped function
- f( x , y ) = sin ( x2 + y2 )
- The examples given here are written in Basic and are therefore rather slow.
- Example 1 (31x31 data array and requesting 10 contour levals) took about 5
- minutes to draw.
-
- ****** Demo FORTRAN-77 program *******
-
- program demo
- implicit none
- c
- c The follwoing is a simplistic application of the CONREC routine.
- c A mathematical function is evaluated over a regular grid of points
- c on a computer raster graphics screen.
- c
- c Paul D. Bourke
- c
- integer*4 pxmin,pymin,pxmax,pymax
- parameter (pxmin = 10,pymin = 10,pxmax = 460,pymax = 300)
- integer*4 nx,ny
- parameter (nx = 100,ny = 50)
- integer*4 nc
- parameter (nc = 10)
- c
- real*4 d(0:nx,0:ny),x(0:nx),y(0:ny),z(1:nc)
- real*4 x1,y1,x2,y2
- real*4 zmax,zmin
- integer*4 i,j
- c
- c Create an artificial data surface and calculate the
- c surface bounds for choosing the contour levels.
- c
- zmin = 1.0e30
- zmax = -1.0e30
- do 200 i=0,nx
- do 100 j=0,ny
- d(i,j) = i * j
- zmin = min(zmin,d(i,j))
- zmax = max(zmax,d(i,j))
- 100 continue
- 200 continue
- c
- c Set coordinates in Y array suitable for
- c automatic plotting on the graphics screen
- c
- do 300 j=0,ny
- y(j) = pymax - j * (pymax - pymin) / float(ny)
- 300 continue
- c
- c Set coordinates in X array suitable for
- c automatic plotting on the graphics screen
- c
- do 400 i=0,nx
- x(i) = i * (pxmax - pxmin) / float(nx) + pxmin
- 400 continue
- c
- c Set a full contingent of contour levels
- c
- do 500 i=1,nc
- z(i) = i * (zmax - zmin) / (nc + 1)
- 500 continue
- c
- c Draw a border around the contour plot
- c
- x1 = pxmin
- y1 = pymin
- x2 = pxmax
- y2 = pymax
- call vecout(x1,y1,x1,y2,0.0)
- call vecout(x1,y2,x2,y2,0.0)
- call vecout(x2,y2,x2,y1,0.0)
- call vecout(x2,y1,x1,y1,0.0)
- c
- c Call the contouring routine
- c
- call conrec(d,0,nx,0,ny,x,y,nc,z)
- pause
- c
- end
-
- ****** FORTRAN-77 CODE *******
-
- c
- c======================================================================
- c
- c CONREC is a contouring subroutine for rectangularily spaced data.
- c
- c It emits calls to a line drawing subroutine supplied by the user
- c which draws a contour map corresponding to real*4data on a randomly
- c spaced rectangular grid. The coordinates emitted are in the same
- c units given in the x() and y() arrays.
- c
- c Any number of contour levels may be specified but they must be
- c in order of increasing value.
- c
- c subroutine conrec(d,ilb,iub,jlb,jub,x,y,nc,z)
- c real*4 d(ilb:iub,jlb:jub) ! matrix of data to contour
- c integer ilb,iub,jlb,jub ! index bounds of data matrix
- c real*4 x(ilb:iub) ! data matrix column coordinates
- c real*4 y(jlb,jub) ! data matrix row coordinates
- c integer nc ! number of contour levels
- c real*4 z(1:nc) ! contour levels in increasing order
- c
- subroutine conrec(d,ilb,iub,jlb,jub,x,y,nc,z)
- real*4 d(ilb:iub,jlb:jub)
- integer ilb,iub,jlb,jub
- real*4 x(ilb:iub)
- real*4 y(jlb:jub)
- integer nc
- real*4 z(1:nc)
- c
- c Local declarations
- c
- real*4 h(0:4)
- integer sh(0:4)
- real*4 xh(0:4),yh(0:4)
- integer im(1:4),jm(1:4)
- integer case
- integer castab(-1:1,-1:1,-1:1)
- integer p1,p2
- c
- c Data
- c
- data im/0,1,1,0/
- data jm/0,0,1,1/
- data castab/0,0,9, 0,1,5, 7,4,8,
- 1 0,3,6, 2,3,2, 6,3,0,
- 2 8,4,7, 5,1,0, 9,0,0/
- c
- c Use statement functions for the line intersections
- c
- xsect(p1,p2) = (h(p2)*xh(p1)-h(p1)*xh(p2))/(h(p2)-h(p1))
- ysect(p1,p2) = (h(p2)*yh(p1)-h(p1)*yh(p2))/(h(p2)-h(p1))
- c
- c Scan the arrays, top down, left to right within rows
- c
- 20 do 100 j=jub-1,jlb,-1
- do 90 i=ilb,iub-1
- dmin = min(d(i,j),d(i,j+1),d(i+1,j),d(i+1,j+1))
- dmax = max(d(i,j),d(i,j+1),d(i+1,j),d(i+1,j+1))
- if (dmax.ge.z(1) .and. dmin.le.z(nc)) then
- do 80 k=1,nc
- if (z(k).ge.dmin .and. z(k).le.dmax) then
- do 22 m=4,0,-1
- if (m.gt.0) then
- h(m)=d(i+im(m),j+jm(m))-z(k)
- xh(m)=x(i+im(m))
- yh(m)=y(j+jm(m))
- else
- h(0)=0.25*(h(1)+h(2)+h(3)+h(4))
- xh(0)=0.5*(x(i)+x(i+1))
- yh(0)=0.5*(y(j)+y(j+1))
- endif
- if (h(m).gt.0.0) then
- sh(m)=+1
- else if (h(m).lt.0.0) then
- sh(m)=-1
- else
- sh(m)=0
- endif
- 22 continue
- c
- c Note: at this stage the relative heights of the corners and the
- c centre are in the h array, and the corresponding coordinates are
- c in the xh and yh arrays. The centre of the box is indexed by 0
- c and the 4 corners by 1 to 4 as shown below.
- c Each triangle is then indexed by the parameter m, and the 3
- c vertices of each triangle are indexed by parameters m1,m2,and m3.
- c It is assumed that the centre of the box is always vertex 2 though
- c this isimportant only when all 3 vertices lie exactly on the same
- c contour level, in which case only the side of the box is drawn.
- c
- c
- c vertex 4 +-------------------+ vertex 3
- c | \ / |
- c | \ m-3 / |
- c | \ / |
- c | \ / |
- c | m=2 X m=2 | the centre is vertex 0
- c | / \ |
- c | / \ |
- c | / m=1 \ |
- c | / \ |
- c vertex 1 +-------------------+ vertex 2
- c
- c
- c
- c Scan each triangle in the box
- c
- do 60 m=1,4
- m1=m
- m2=0
- if (m.ne.4) then
- m3=m+1
- else
- m3=1
- endif
- case = castab(sh(m1),sh(m2),sh(m3))
- if (case.ne.0) then
- goto (31,32,33,34,35,36,37,38,39),case
- c
- c Case 1 - Line between vertices 1 and 2
- c
- 31 x1=xh(m1)
- y1=yh(m1)
- x2=xh(m2)
- y2=yh(m2)
- goto 40
- c
- c Case 2 - Line between vertices 2 and 3
- c
- 32 x1=xh(m2)
- y1=yh(m2)
- x2=xh(m3)
- y2=yh(m3)
- goto 40
- c
- c Case 3 - Line between vertices 3 and 1
- c
- 33 x1=xh(m3)
- y1=yh(m3)
- x2=xh(m1)
- y2=yh(m1)
- goto 40
- c
- c Case 4 - Line between vertex 1 and side 2-3
- c
- 34 x1=xh(m1)
- y1=yh(m1)
- x2=xsect(m2,m3)
- y2=ysect(m2,m3)
- goto 40
- c
- c Case 5 - Line between vertex 2 and side 3-1
- c
- 35 x1=xh(m2)
- y1=yh(m2)
- x2=xsect(m3,m1)
- y2=ysect(m3,m1)
- goto 40
- c
- c Case 6 - Line between vertex 3 and side 1-2
- c
- 36 x1=xh(m3)
- y1=yh(m3)
- x2=xsect(m1,m2)
- y2=ysect(m1,m2)
- goto 40
- c
- c Case 7 - Line between sides 1-2 and 2-3
- c
- 37 x1=xsect(m1,m2)
- y1=ysect(m1,m2)
- x2=xsect(m2,m3)
- y2=ysect(m2,m3)
- goto 40
- c
- c Case 8 - Line between sides 2-3 and 3-1
- c
- 38 x1=xsect(m2,m3)
- y1=ysect(m2,m3)
- x2=xsect(m3,m1)
- y2=ysect(m3,m1)
- goto 40
- c
- c Case 9 - Line between sides 3-1 and 1-2
- c
- 39 x1=xsect(m3,m1)
- y1=ysect(m3,m1)
- x2=xsect(m1,m2)
- y2=ysect(m1,m2)
- goto 40
- 40 call vecout(x1,y1,x2,y2,z(k))
- endif
- 60 continue
- endif
- 80 continue
- endif
- 90 continue
- 100 continue
- return
- end
- c
- c======================================================================
- c
- c This is a sample vector output routine. For a local environment
- c either replace the VECOUT call in the main line, or better
- c replace the contents of this subroutine between the *'s shown.
- c
- c There is often the requirement to distinguish each contour
- c line with a different colour or a different line style. This
- c can be done in many ways using the contour values z for a
- c particular line segment.
- c
- subroutine vecout(x1,y1,x2,y2,z)
- implicit none
- real*4 x1,y1,x2,y2,z
- c
- c***** Replace from here
- c
- c The following should be ignored since it is specific to
- c the version of FORTRAN running on the Macintosh microcomputer
- c on which this particular example was written.
- c
- INTEGER LINETO
- PARAMETER (LINETO=Z'89109000')
- INTEGER MOVETO
- PARAMETER (MOVETO=Z'89309000')
- call toolbx(MOVETO,nint(x1),nint(y1))
- call toolbx(LINETO,nint(x2),nint(y2))
- c
- c***** To here
- c
- return
- end
-
- ****** IBM BASIC CODE *******
-
- 1000 REM
- ====================================================================
- 1010 REM Documentation
- 1020 REM =============
- 1030 REM
- 1040 REM Originally written in FORTRAN-77
- 1050 REM Translated to BASICA on the IBM-PC microcomputer
- 1060 REM By Paul D. Bourke, August 1987
- 1070 REM
- 1080 REM Input variables to CONREC
- 1090 REM d(0:iub,0:jub) matrix for the data surface height values
- 1100 REM iub, jub index bounds of the data array
- 1110 REM x(0:iub) data array for column coordinates
- 1120 REM y(0:jub) data array for row coordinates
- 1130 REM nc number of contour levels
- 1140 REM z(0:nc-1) contour levels in increasing order
- 1150 REM It is assumed that the logical variables TRUE and FALSE are
- 1160 REM either available or have been defined in the main line.
- 1170 REM
- 1180 REM NOTE: All arrays have a minimum index of 0
- 1190 REM
- 1200 REM Local declarations for CONREC
- 1210 REM =============================
- 1220 DIM H(4) ' relative heights of the box above contour
- 1230 DIM ISH(4) ' sign of h()
- 1240 DIM XH(4) ' x coordinates of box
- 1250 DIM YH(4) ' y coordinates of box
- 1260 DIM IM(3) ' mapping from vertex numbers to x offsets
- 1270 IM(0)=0 : IM(1)=1 : IM(2)=1 : IM(3)=0
- 1280 DIM JM(3) ' mapping from vertex numbers to y offsets
- 1290 JM(0)=0 : JM(1)=0 : JM(2)=1 : JM(3)=1
- 1300 DIM CASTAB(2,2,2)
- 1310 DATA 0,0,8,0,2,5,7,6,9, 0,3,4,1,3,1,4,3,0, 9,6,7,5,2,0,8,0,0
- 1320 FOR K=0 TO 2
- 1330 FOR J=0 TO 2
- 1340 FOR I=0 TO 2
- 1350 READ CASTAB(K,J,I)
- 1360 NEXT I
- 1370 NEXT J
- 1380 NEXT K
- 1390 REM
- 1400 REM Check the input parameters for validity
- 1410 REM PRMERR should be tested by the calling routine and
- 1420 REM MSG$ printed if PRMERR is TRUE
- 1430 REM
- 1440 PRMERR = FALSE
- 1450 IF (IUB<=0 OR JUB<=0) THEN PRMERR = TRUE
- 1460 IF (NC<=0) THEN PRMERR = TRUE
- 1470 FOR K=1 TO NC-1
- 1480 IF (Z(K)<=Z(K-1)) THEN PRMERR = TRUE
- 1490 NEXT K
- 1500 IF (PRMERR) THEN MSG$ = "Error in input parameters" : RETURN
- 1510 REM
- 1520 REM Scan the array, top down, left to right
- 1530 REM =======================================
- 1540 FOR J=JUB-1 TO 0 STEP -1
- 1550 FOR I=0 TO IUB-1
- 1560 REM Find the lowest vertex in the rectangle
- 1570 IF (D(I,J)<D(I,J+1)) THEN DMIN = D(I,J) ELSE DMIN = D(I,J+1)
- 1580 IF (D(I+1,J)<DMIN) THEN DMIN = D(I+1,J)
- 1590 IF (D(I+1,J+1)<DMIN) THEN DMIN = D(I+1,J+1)
- 1600 REM Find the highest vertex in the rectangle
- 1610 IF (D(I,J)>D(I,J+1)) THEN DMAX = D(I,J) ELSE DMAX = D(I,J+1)
- 1620 IF (D(I+1,J)>DMAX) THEN DMAX = D(I+1,J)
- 1630 IF (D(I+1,J+1)>DMAX) THEN DMAX = D(I+1,J+1)
- 1640 IF (DMAX<Z(0) OR DMIN>Z(NC-1)) THEN GOTO 2700
- 1650 REM
- 1660 REM Draw each contour within this box
- 1670 FOR K=0 TO NC-1
- 1680 IF ((Z(K)<DMIN) OR (Z(K)>DMAX)) THEN GOTO 2690
- 1690 FOR M=4 TO 0 STEP -1
- 1700 IF M>0 THEN GOTO 1720
- 1710 IF M=0 THEN GOTO 1770
- 1720 REM m > 0
- 1730 H(M) = D(I+IM(M-1),J+JM(M-1))-Z(K)
- 1740 XH(M) = X(I+IM(M-1))
- 1750 YH(M) = Y(J+JM(M-1))
- 1760 GOTO 1820
- 1770 REM m = 0
- 1780 H(0) = (H(1)+H(2)+H(3)+H(4))/4
- 1790 XH(0) = (X(I)+X(I+1))/2
- 1800 YH(0) = (Y(J)+Y(J+1))/2
- 1810 GOTO 1820
- 1820 IF H(M) > 0 THEN ISH(M) = 2
- 1830 IF H(M) = 0 THEN ISH(M) = 1
- 1840 IF H(M) < 0 THEN ISH(M) = 0
- 1850 NEXT M
- 1860 REM
- 1870 REM Scan each triangle in the box
- 1880 FOR M=1 TO 4
- 1890 M1 = M
- 1900 M2 = 0
- 1910 M3 = M+1
- 1920 IF (M3 = 5) THEN M3 = 1
- 1930 REM
- 1940 REM Select the type of line/plane intersection
- 1950 CASE = CINT(CASTAB(ISH(M1),ISH(M2),ISH(M3)))
- 1960 IF CASE = 0 THEN GOTO 2680
- 1970 IF CASE = 1 THEN GOTO 2060
- 1980 IF CASE = 2 THEN GOTO 2120
- 1990 IF CASE = 3 THEN GOTO 2180
- 2000 IF CASE = 4 THEN GOTO 2240
- 2010 IF CASE = 5 THEN GOTO 2300
- 2020 IF CASE = 6 THEN GOTO 2360
- 2030 IF CASE = 7 THEN GOTO 2420
- 2040 IF CASE = 8 THEN GOTO 2480
- 2050 IF CASE = 9 THEN GOTO 2540
- 2060 REM Case 1: Line between vertices m1 and m2
- 2070 X1 = XH(M1)
- 2080 Y1 = YH(M1)
- 2090 X2 = XH(M2)
- 2100 Y2 = YH(M2)
- 2110 GOTO 2650
- 2120 REM Case 2: Line between vertices m2 and m3
- 2130 X1 = XH(M2)
- 2140 Y1 = YH(M2)
- 2150 X2 = XH(M3)
- 2160 Y2 = YH(M3)
- 2170 GOTO 2650
- 2180 REM Case 3: Line between vertices m3 and m1
- 2190 X1 = XH(M3)
- 2200 Y1 = YH(M3)
- 2210 X2 = XH(M1)
- 2220 Y2 = YH(M1)
- 2230 GOTO 2650
- 2240 REM Case 4: Line between vertex m1 and side m2-m3
- 2250 X1 = XH(M1)
- 2260 Y1 = YH(M1)
- 2270 X2 = (H(M3)*XH(M2)-H(M2)*XH(M3))/(H(M3)-H(M2))
- 2280 Y2 = (H(M3)*YH(M2)-H(M2)*YH(M3))/(H(M3)-H(M2))
- 2290 GOTO 2650
- 2300 REM Case 5: Line between vertex m2 and side m3-m1
- 2310 X1 = XH(M2)
- 2320 Y1 = YH(M2)
- 2330 X2 = (H(M1)*XH(M3)-H(M3)*XH(M1))/(H(M1)-H(M3))
- 2340 Y2 = (H(M1)*YH(M3)-H(M3)*YH(M1))/(H(M1)-H(M3))
- 2350 GOTO 2650
- 2360 REM Case 6: Line between vertex m3 and side m1-m2
- 2370 X1 = XH(M3)
- 2380 Y1 = YH(M3)
- 2390 X2 = (H(M2)*XH(M1)-H(M1)*XH(M2))/(H(M2)-H(M1))
- 2400 Y2 = (H(M2)*YH(M1)-H(M1)*YH(M2))/(H(M2)-H(M1))
- 2410 GOTO 2650
- 2420 REM CASE 7: Line between sides m1-m2 and m2-m3
- 2430 X1 = (H(M2)*XH(M1)-H(M1)*XH(M2))/(H(M2)-H(M1))
- 2440 Y1 = (H(M2)*YH(M1)-H(M1)*YH(M2))/(H(M2)-H(M1))
- 2450 X2 = (H(M3)*XH(M2)-H(M2)*XH(M3))/(H(M3)-H(M2))
- 2460 Y2 = (H(M3)*YH(M2)-H(M2)*YH(M3))/(H(M3)-H(M2))
- 2470 GOTO 2650
- 2480 REM Case 8: Line between sides m2-m3 and m3-m1
- 2490 X1 = (H(M3)*XH(M2)-H(M2)*XH(M3))/(H(M3)-H(M2))
- 2500 Y1 = (H(M3)*YH(M2)-H(M2)*YH(M3))/(H(M3)-H(M2))
- 2510 X2 = (H(M1)*XH(M3)-H(M3)*XH(M1))/(H(M1)-H(M3))
- 2520 Y2 = (H(M1)*YH(M3)-H(M3)*YH(M1))/(H(M1)-H(M3))
- 2530 GOTO 2650
- 2540 REM Case 9: Line between sides m3-m1 and m1-m2
- 2550 X1 = (H(M1)*XH(M3)-H(M3)*XH(M1))/(H(M1)-H(M3))
- 2560 Y1 = (H(M1)*YH(M3)-H(M3)*YH(M1))/(H(M1)-H(M3))
- 2570 X2 = (H(M2)*XH(M1)-H(M1)*XH(M2))/(H(M2)-H(M1))
- 2580 Y2 = (H(M2)*YH(M1)-H(M1)*YH(M2))/(H(M2)-H(M1))
- 2590 REM This is where a contour line segment of value z(i)
- 2600 REM is drawn between points (x1,y1) and (x2,y2)
- 2610 REM The exact details can vary depending on the particular
- 2620 REM graphics capabilities available.
- 2630 REM If colour is available then each contour level could
- 2640 REM be drawn in a new colour
- 2650 line (x1,y1)-(x2,y2)
- 2660 NEXT M
- 2670 NEXT K
- 2680 NEXT I
- 2690 NEXT J
- 2700 RETURN
- 2710 REM ===================================================================
-